package edu.tjut.tjutcommunity.controller;

import com.alibaba.fastjson.JSON;
import edu.tjut.tjutcommunity.entity.*;
import edu.tjut.tjutcommunity.handler.LoginHandler;
import edu.tjut.tjutcommunity.httpInterface.KcbxxHttp;
import edu.tjut.tjutcommunity.httpInterface.KxjsHttp;
import edu.tjut.tjutcommunity.service.KbService;
import edu.tjut.tjutcommunity.service.UserService;
import edu.tjut.tjutcommunity.utils.UserUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import static edu.tjut.tjutcommunity.utils.PairUtils.getPair;

@RestController
public class SsfwController {

    final KxjsHttp kxjsHttp;

    final KcbxxHttp kcbxxHttp;

    final UserService userService;

    final KbService kbService;

    @Resource
    private final StringRedisTemplate stringRedisTemplate;

    public SsfwController(KxjsHttp kxjsHttp, KcbxxHttp kcbxxHttp, UserService userService, StringRedisTemplate stringRedisTemplate, KbService kbService) {
        this.kxjsHttp = kxjsHttp;
        this.kcbxxHttp = kcbxxHttp;
        this.userService = userService;
        this.stringRedisTemplate = stringRedisTemplate;
        this.kbService = kbService;
    }

    @Deprecated
    @PostMapping("/kxjs")
    public Message kxjs(@RequestBody KxjsQureyInfo kxjsQureyInfo) {
        //通过token获取redis中的cookie
        String stuId = UserUtil.getCurStuId();
        String cookieJson = stringRedisTemplate.opsForValue().get(stuId + "_cookie");
        if (cookieJson == null || cookieJson.isEmpty()) return Message.cookieHasExpired();
        UserCookie userCookie = JSON.parseObject(cookieJson, UserCookie.class);
        //id,jsession
        String cookie = userCookie.getCOOKIE_IPLANETDIRECTORYPRO() + "; " + userCookie.getCOOKIE_JSESSIONID_SSFW();
        String kxjs = kxjsHttp.kxjs(cookie, kxjsQureyInfo);
        Document doc = Jsoup.parse(kxjs);
        Elements select = doc.select("tr[class=t_con]");
        ArrayList<KxjsResponse> kxjsResponses = new ArrayList<>();
        select.eachText().forEach(element -> {
            String[] res = element.split(" ");
            kxjsResponses.add(new KxjsResponse(res[0], res[1], res[2], res[3], res[4], res[5], res[6], res[8]));
        });
        if (kxjsResponses.isEmpty()) return Message.empty();
        return Message.ok(kxjsResponses);
    }

    static final String base_kcb_url = "http://ssfw.tjut.edu.cn/ssfw/pkgl/kcbxx/4/";

    @Deprecated
    @PostMapping("/kcbxx")
    public Message kcbxx(@RequestBody KcbxxQueryInfo kcbxxQueryInfo) {
        //通过token获取redis中的cookie
        String stuId = UserUtil.getCurStuId();
        User user = userService.getUserByStuId(stuId);
        //查询redis，如果redis有则直接返回，没有则查询数据库，还没有就执行请求学校接口。
        String year = kcbxxQueryInfo.getYear();
        String semester = kcbxxQueryInfo.getSemester();
        String redisQuery = stuId + "_kb_" + year + "_" + semester;
        String kbJson = stringRedisTemplate.opsForValue().get(redisQuery);
        if (kbJson != null) {
            //直接返回结果
            Kbxx kbxx = JSON.parseObject(kbJson, Kbxx.class);
            HashMap<String, Object> map = new HashMap<>();
            map.put("title", kbxx.getTitle());
            map.put("course", kbxx.getCourses());
            map.put("nonCourse", kbxx.getNotCourse());

            return Message.ok(map);
        }
        //未查询到信息，查询mysql
        kbJson = kbService.getKbJsonByUidAndSemesterAndYear(user.getUid(), kcbxxQueryInfo);
        if (kbJson != null) {
            Kbxx kbxx = JSON.parseObject(kbJson, Kbxx.class);
            //更新redis
            stringRedisTemplate.opsForValue().set(redisQuery, kbJson, 7, TimeUnit.DAYS);
            HashMap<String, Object> map = new HashMap<>();
            map.put("title", kbxx.getTitle());
            map.put("course", kbxx.getCourses());
            map.put("nonCourse", kbxx.getNotCourse());
            return Message.ok(map);
        }
        //未查询到信息，查询学校接口并更新


        String cookieJson = stringRedisTemplate.opsForValue().get(stuId + "_cookie");
        if (cookieJson == null || cookieJson.isEmpty()) return Message.cookieHasExpired();
        UserCookie userCookie = JSON.parseObject(cookieJson, UserCookie.class);
        //获取到userCookie后，获取师生服务cookie
        boolean flag = true;
        int count = 0;
        Kbxx kbxx = null;
        while (flag && count <= 5) {
            try {
                //获取师生服务的cookie
                LoginHandler.setSSFWCookie(userCookie);
                kbxx = getKbxx(userCookie, year, semester);
                if (kbxx != null) {
                    flag = false;
                    //更新mysql
                    kbService.addKbxx(kbxx, user);
                    //更新redis
                    stringRedisTemplate.opsForValue().set(redisQuery, JSON.toJSONString(kbxx), 7, TimeUnit.DAYS);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //尝试获取选课结果
            count++;
        }
        if (kbxx == null) return Message.failed("课表获取失败");
        HashMap<String, Object> map = new HashMap<>();
        map.put("title", kbxx.getTitle());
        map.put("course", kbxx.getCourses());
        map.put("nonCourse", kbxx.getNotCourse());
        return Message.ok(map);
    }

    /**
     * 根据user信息和年份学期获取课表信息。
     *
     * @param userCookie
     * @param year
     * @param semester
     * @return
     */
    private Kbxx getKbxx(UserCookie userCookie, String year, String semester) {
        String cookie = userCookie.getCOOKIE_IPLANETDIRECTORYPRO() + "; " + userCookie.getCOOKIE_JSESSIONID_SSFW();
        String url = base_kcb_url + year + "-" + semester + ".do";
        //标题
        String title = null;
        ArrayList<CourseInformation> courses = null;
        //未安排课程
        ArrayList<CourseInformation> notCourse = null;
        String kcbxx = kcbxxHttp.kcbxx(cookie, url);
        if (kcbxx == null) return null;
        Document doc = Jsoup.parse(kcbxx);

        courses = new ArrayList<>();
        Element titleElement = doc.getElementsByTag("caption").get(0);

        title = titleElement.ownText();
        Elements trs = doc.getElementsByTag("tr");
        getTrs(courses, trs);
        if (courses.isEmpty()) return null;
        notCourse = new ArrayList<>();
        getNotCourse(trs, notCourse);
        return new Kbxx(title, courses, notCourse, year, semester);
    }

    private void getNotCourse(Elements trs, ArrayList<CourseInformation> notCourse) {
        if (trs.size() > 12) {
            Element tr = trs.get(12);
            Elements sonTrs = tr.getElementsByTag("tr");
            for (int i = 2; i < sonTrs.size(); i++) {
                CourseInformation c = new CourseInformation();
                c.setCourseName(sonTrs.get(i).children().get(0).text().split("\\[")[0]);
                c.setWeeks(sonTrs.get(i).children().get(1).text());
                c.setTeacherName(sonTrs.get(i).children().get(2).text());
                c.setNote(sonTrs.get(i).children().get(3).text());
                notCourse.add(c);
            }
        }
    }

    private void getTrs(ArrayList<CourseInformation> courses, Elements trs) {
        for (int i = 0; i < 12; i++) {
            if (i % 2 == 0) continue;
            //第i/2节
            Elements tds = trs.get(i).children();
            for (int j = 2; j < tds.size(); j++) {
                String text = tds.get(j).text();
                if (!text.equals("")) {
                    String[] s = text.split(" ");
                    CourseInformation c = new CourseInformation();
                    c.setCourseName(s[0].split("\\[")[0]);
                    c.setWeeks(s[1]);
                    c.setTimes(s[2]);
                    c.setTeacherName(s[3]);
                    c.setLocation(s[4] + s[5]);
                    c.setDay(j - 1);
                    c.setTime((i + 1) / 2);
                    courses.add(c);
                    if (s.length > 6) {
                        //单双周的课
                        CourseInformation c2 = new CourseInformation();
                        c2.setCourseName(s[6].split("\\[")[0]);
                        c2.setWeeks(s[7]);
                        c2.setTimes(s[8]);
                        c2.setTeacherName(s[9]);
                        c2.setLocation(s[10] + s[11]);
                        c.setDay(j - 1);
                        c.setTime((i + 1) / 2);
                        courses.add(c2);
                    }
                }
            }
        }
    }






}
